conf = require("../config")
if not conf.lspconfig_nvim.enabled then return {} end

local lsp = {
  'basedpyright',
  'clangd',
  'jsonls',
  'lua_ls',
  'marksman',
  'rust_analyzer',
  'svlangserver',
  'texlab',
}

vim.lsp.enable(lsp)

vim.api.nvim_create_autocmd('LspAttach', {
  group = vim.api.nvim_create_augroup('lsp-attach', { clear = true}),
  callback = function (event)
    -- obtain LSP client
    local client = vim.lsp.get_client_by_id(event.data.client_id)

    -- [basic keymaps]
    vim.keymap.set('n', 'gD',        vim.lsp.buf.declaration, {buffer = event.buf, desc = 'jump to the declaration'})
    -- vim.keymap.set('n', 'gd',        vim.lsp.buf.definition,              bufopts("jumps to the definition"))
    vim.keymap.set('n', '<space>hh', vim.lsp.buf.hover, {buffer = event.buf, desc = 'display hover information'})
    -- vim.keymap.set('n', 'gi',        vim.lsp.buf.implementation,          bufopts("list all the implementations"))
    vim.keymap.set('n', '<space>ss',  vim.lsp.buf.signature_help, {buffer = event.buf, desc = 'display signature information'})
    vim.keymap.set('n', '<space>wa', vim.lsp.buf.add_workspace_folder, {buffer = event.buf, desc = 'add the folder at path to the workspace folders'})
    vim.keymap.set('n', '<space>wr', vim.lsp.buf.remove_workspace_folder, {buffer = event.buf, desc = 'remove the folder at path from the workspace folders'})
    vim.keymap.set('n', '<space>wl', function()
      print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
    end, {buffer = event.buf, desc = 'list workspace folders'})
    vim.keymap.set('n', '<space>D',  vim.lsp.buf.type_definition, {buffer = event.buf, desc = 'jump to the definition of the type'})
    vim.keymap.set('n', '<space>rn', vim.lsp.buf.rename, {buffer = event.buf, desc = 'rename all references to the symbol'})
    vim.keymap.set('n', '<space>ca', vim.lsp.buf.code_action, {buffer = event.buf, desc = 'select a code action available'})
      -- vim.keymap.set('n', 'gr',        vim.lsp.buf.references,              bufopts("list all the references to the symbol"))
      vim.keymap.set("n", "<space>f", function()
        vim.lsp.buf.format({ async = true })
      end, {buffer = event.buf, desc = 'format a buffer'})

    -- folding
    if client and client:supports_method 'textDocument/foldingRange' then
      local win = vim.api.nvim_get_current_win()
      vim.wo[win][0].foldexpr = 'v:lua.vim.lsp.foldexpr()'
    end

    -- Inlay hint
    if client and client:supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint) then
      -- vim.lsp.inlay_hint.enable()
      vim.keymap.set('n', '<space>th', function()
        vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf })
      end, { buffer = event.buf, desc = 'LSP: Toggle Inlay Hints' })
    end

    -- Highlight words under cursor
    if client and client:supports_method(vim.lsp.protocol.Methods.textDocument_documentHighlight) and vim.bo.filetype ~= 'bigfile' then
      local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false })
      vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
        buffer = event.buf,
        group = highlight_augroup,
        callback = vim.lsp.buf.document_highlight,
      })

      vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
        buffer = event.buf,
        group = highlight_augroup,
        callback = vim.lsp.buf.clear_references,
      })

      vim.api.nvim_create_autocmd('LspDetach', {
        group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }),
        callback = function(event2)
          vim.lsp.buf.clear_references()
          vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf }
          -- vim.cmd 'setl foldexpr <'
        end,
      })
    end

    -- diagnostics
    vim.diagnostic.config({
      virtual_text = false,
      signs = {
        text = {
          [vim.diagnostic.severity.ERROR] = '󰅚 ',
          [vim.diagnostic.severity.WARN] = '󰀪 ',
          [vim.diagnostic.severity.HINT] = '󰌶 ',
          [vim.diagnostic.severity.INFO] = ' ',
        },
        severity = { min = vim.diagnostic.severity.ERROR }, -- only display ERROR
      },
      -- signs = true,
      -- underline = true,
      underline = {
        severity = { min = vim.diagnostic.severity.ERROR }, -- only display ERROR
      },
      update_in_insert = false,
      severity_sort = false,
    })
    vim.keymap.set('n', '<space>e', vim.diagnostic.open_float,  {buffer = event.buf, desc = 'show diagnostics in a floating window'})
    vim.keymap.set('n', '[g',       vim.diagnostic.goto_prev, {buffer = event.buf, desc = 'move to the previous diagnostic'})
    vim.keymap.set('n', ']g',       vim.diagnostic.goto_next, {buffer = event.buf, desc = 'move to the next diagnostic'})
    vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist, {buffer = event.buf, desc = 'add buffer diagnostics to the location list'})

    local border = 'rounded'
    -- LSP settings
    -- local handlers =  {
    --   ["textDocument/hover"] =  vim.lsp.with(vim.lsp.handlers.hover, {border = border}),
    --   ["textDocument/signatureHelp"] =  vim.lsp.with(vim.lsp.handlers.signature_help, {border = border }),
    -- }

    -- To instead override globally
    local orig_util_open_floating_preview = vim.lsp.util.open_floating_preview
    function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...)
      opts = opts or {}
      opts.border = opts.border or border
      return orig_util_open_floating_preview(contents, syntax, opts, ...)
    end

  end,
})
